package com.lemon.boot.service.impl;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.NumberUtil;
import com.lemon.boot.common.base.BaseServiceImpl;
import com.lemon.boot.common.consts.ApiConst;
import com.lemon.boot.common.entity.LoginUserDetail;
import com.lemon.boot.common.enums.DeleteEnum;
import com.lemon.boot.common.enums.StatusEnum;
import com.lemon.boot.common.utils.JwtUtil;
import com.lemon.boot.dao.DeptDAO;
import com.lemon.boot.dto.DeptDTO;
import com.lemon.boot.po.DeptPO;
import com.lemon.boot.service.IDeptService;
import com.lemon.boot.vo.TreeDeptVO;
import com.lemon.boot.vo.TreeSelectVO;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 部门表 业务实现类
 *
 * @author Lemon
 * @since 2024-02-29
 */
@Log4j2
@Service
public class DeptServiceImpl extends BaseServiceImpl<DeptDAO, DeptPO, DeptDTO> implements IDeptService {
    @Override
    @Transactional
    public String add(DeptPO deptPO) {
        //1.当前用户信息
        LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.判断用户是否存在
        Dict dict = this.exists(deptPO, currentUser);
        if (dict.getBool("success")) {
            return dict.getStr("msg");
        }

        //3.设置默认值
        deptPO.setTenantId(currentUser.getTenantId());

        //4.执行添加
        String result = super.add(deptPO);

        //5.修改 tree_link_id
        this.update().set("tree_link_id", getTreeLinkId(deptPO)).eq("id", deptPO.getId()).update();

        return result;
    }

    @Override
    public String del(Long id) {
        //1.获取要删除的tree_link_id
        DeptPO deptPO = this.query().select("tree_link_id").eq("id", id).last("limit 1").one();
        if (deptPO != null && StringUtils.hasText(deptPO.getTreeLinkId())) {
            //2.根据 tree_link_id 删除数据
            this.update().likeRight("tree_link_id", deptPO.getTreeLinkId()).remove();
        }
        return "删除成功！";
    }

    @Override
    @Transactional
    public String edit(DeptPO deptPO) {
        //1.当前用户信息
        LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.判断用户是否存在
        Dict dict = this.exists(deptPO, currentUser);
        if (dict.getBool("success")) {
            return dict.getStr("msg");
        }

        //3.不能修改同级部门
        if (deptPO.getId().equals(deptPO.getParentId())) {
            return "同一部门不能为父子关系";
        }

        //4.验证父子部门关系
        if (!ApiConst.SUPER_PARENT_ID.equals(deptPO.getParentId())) {
            DeptPO parentDept = this.query().select("tree_link_id").eq("id", deptPO.getParentId()).last("limit 1").one();
            List<Long> parentIdList = Arrays.stream(parentDept.getTreeLinkId().split(",")).map(NumberUtil::parseLong).collect(Collectors.toList());
            if (parentIdList.contains(deptPO.getId())) {
                return "父子部门错误";
            }
        }

        //5.设置默认值
        deptPO.setUpdateBy(currentUser.getName());

        //6.保存之前的 tree_link_id
        if (!StringUtils.hasText(deptPO.getTreeLinkId())) {
            DeptPO dept = this.query().select("tree_link_id").eq("id", deptPO.getId()).last("limit 1").one();
            if (dept != null && StringUtils.hasText(dept.getTreeLinkId())) {
                deptPO.setTreeLinkId(dept.getTreeLinkId());
            }
        }
        String oldTreeLinkId = deptPO.getTreeLinkId();

        //7.设置新的 tree_link_id
        String newTreeLinkId = getTreeLinkId(deptPO);

        //8.根据 tree_link_id 获取数据
        List<DeptPO> deptList = this.query().select("id", "tree_link_id").likeRight("tree_link_id", oldTreeLinkId).list();
        if (!CollectionUtils.isEmpty(deptList)) {
            deptList.forEach(item -> {
                item.setTreeLinkId(item.getTreeLinkId().replace(oldTreeLinkId, newTreeLinkId));
                item.setUpdateBy(currentUser.getName());
            });
            this.updateBatchById(deptList);
        }

        return super.edit(deptPO);
    }

    /**
     * 判断部门名称是否重复
     *
     * @param deptPO
     * @param currentUser
     * @return
     */
    private Dict exists(DeptPO deptPO, LoginUserDetail currentUser) {
        //1.判断是否存在
        boolean exists = this.query().select("1")
                .eq("name", deptPO.getName())
                .eq("tenant_id", currentUser.getTenantId())
                .ne(deptPO.getId() != null, "id", deptPO.getId())
                .last("limit 1")
                .exists();

        //2.封装返回结果
        return Dict.create().set("success", exists).set("msg", String.format("部门名称\"%s\"已存在！", deptPO.getName()));
    }

    /**
     * 根据ID获取 tree_link_id
     *
     * @param deptPO
     * @return
     */
    private String getTreeLinkId(DeptPO deptPO) {
        //1.获取 tree_link_id
        if (!StringUtils.hasText(deptPO.getTreeLinkId())) {
            DeptPO dept = this.query().select("tree_link_id").eq("id", deptPO.getId()).last("limit 1").one();
            if (dept != null && StringUtils.hasText(dept.getTreeLinkId())) {
                deptPO.setTreeLinkId(dept.getTreeLinkId());
            }
        }

        //2.设置 tree_link_id 字段
        if (ApiConst.SUPER_PARENT_ID.equals(deptPO.getParentId())) {
            deptPO.setTreeLinkId(String.valueOf(deptPO.getId()));
        } else {
            DeptPO parentDept = this.query().select("tree_link_id").eq("id", deptPO.getParentId()).last("limit 1").one();
            deptPO.setTreeLinkId(String.format("%s,%s", parentDept.getTreeLinkId(), deptPO.getId()));
        }
        return deptPO.getTreeLinkId();
    }

    @Override
    @Transactional
    public String addOrEdit(DeptPO deptPO) {
        return deptPO.getId() == null ? this.add(deptPO) : this.edit(deptPO);
    }

    @Override
    public List<String> getDeptName(Map<String, Object> param) {
        return this.baseMapper.getDeptNameByUserId(param);
    }

    @Override
    public List<TreeDeptVO> list(DeptDTO deptDTO) {
        //1.当前用户
        LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.设置参数
        deptDTO.setTenantId(currentUser.getTenantId());
        deptDTO.setDeleted(DeleteEnum.UNABLE.getDeleted());

        //3.搜索
        if (StringUtils.hasText(deptDTO.getName()) || deptDTO.getStatus() != null) {
            //3.1.根据状态和名称查询部门ID
            List<Long> idList = this.baseMapper.getIdByStatusAndName(deptDTO);
            if (CollectionUtils.isEmpty(idList)) {
                return null;
            }
            deptDTO.setDeptIdList(idList);
        }

        //4.查询数据
        List<TreeDeptVO> treeDeptList = this.baseMapper.getByDeptIdAndTenantId(deptDTO);
        if (CollectionUtils.isEmpty(treeDeptList)) {
            return null;
        }

        //5.根据parent_id分组
        Map<Long, List<TreeDeptVO>> listMap = treeDeptList.stream().collect(groupingBy(TreeDeptVO::getParentId));

        //7.设置子菜单
        List<Long> childIdList = new ArrayList<>();
        treeDeptList.forEach(item -> {
            List<TreeDeptVO> childList = listMap.get(item.getId());
            if (!CollectionUtils.isEmpty(childList)) {
                item.setChildren(childList);
                childIdList.addAll(childList.stream().map(TreeDeptVO::getId).collect(Collectors.toList()));
            }
        });

        //8.获取所有父菜单的数据（因为子菜单以及在父菜单中）
        if (StringUtils.hasText(deptDTO.getName()) || deptDTO.getStatus() != null) {
            return treeDeptList.stream()
                    .filter(item -> deptDTO.getDeptIdList().contains(item.getId()) && !childIdList.contains(item.getId()))
                    .collect(Collectors.toList());
        }
        return treeDeptList.stream().filter(item -> ApiConst.SUPER_PARENT_ID.equals(item.getParentId())).collect(Collectors.toList());
    }

    @Override
    public Map<String, Integer> getDeptNameAndUserCount(Map<String, Object> param) {
        List<Map<String, String>> deptList = this.baseMapper.getDeptNameAndUserCountByUserId(param);
        return deptList.stream().collect(Collectors.toMap(item -> item.get("name"), item -> NumberUtil.parseInt(String.valueOf(item.get("total")))));
    }

    @Override
    public List<TreeSelectVO> getParentByTreeSelect() {
        //1.当前用户
        LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.设置参数
        Map<String, Object> param = ApiConst.enableStatusAndUnableDelete();
        param.put("tenantId", currentUser.getTenantId());

        //3.查询数据
        List<TreeSelectVO> treeDeptList = this.baseMapper.getByTreeSelect(param);
        if (CollectionUtils.isEmpty(treeDeptList)) {
            return Collections.singletonList(new TreeSelectVO().setLabel(ApiConst.SUPER_DEPT_NAME).setValue(ApiConst.SUPER_PARENT_ID));
        }

        //4.根据parent_id分组
        Map<Long, List<TreeSelectVO>> listMap = treeDeptList.stream().collect(groupingBy(TreeSelectVO::getParentId));

        //5.设置子菜单
        treeDeptList.forEach(item -> item.setChildren(listMap.get(item.getValue())));

        //6.获取所有父菜单的数据（因为子菜单以及在父菜单中）
        List<TreeSelectVO> result = treeDeptList.stream().filter(item -> ApiConst.SUPER_PARENT_ID.equals(item.getParentId())).collect(Collectors.toList());

        //7.创建值为-1的顶级部门
        return Collections.singletonList(new TreeSelectVO().setLabel(ApiConst.SUPER_DEPT_NAME).setValue(ApiConst.SUPER_PARENT_ID).setChildren(result));
    }

    @Override
    public List<TreeSelectVO> getByTreeSelectByTenantId(Long tenantId) {
        //1.当前用户
        LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.设置参数
        Map<String, Object> param = ApiConst.enableStatusAndUnableDelete();
        param.put("tenantId", currentUser.getTenantId());

        //3.查询数据
        List<TreeSelectVO> treeDeptList = this.baseMapper.getByTreeSelect(param);
        if (CollectionUtils.isEmpty(treeDeptList)) {
            return null;
        }

        //4.根据parent_id分组
        Map<Long, List<TreeSelectVO>> listMap = treeDeptList.stream().collect(groupingBy(TreeSelectVO::getParentId));

        //5.设置子菜单
        treeDeptList.forEach(item -> item.setChildren(listMap.get(item.getValue())));

        //6.获取所有父菜单的数据（因为子菜单以及在父菜单中）
        return treeDeptList.stream().filter(item -> ApiConst.SUPER_PARENT_ID.equals(item.getParentId())).collect(Collectors.toList());
    }

    /*@Override
    @Transactional
    public String unable(Collection<Long> ids) {
        List<DeptPO> deptList = this.query().select("tree_link_id").in("id",ids).list();
        deptList.stream().map(DeptPO::getTreeLinkId).forEach(item -> {
            this.update().set(StatusEnum.UNABLE.getColumn(), StatusEnum.UNABLE.getStatus()).likeRight("tree_link_id",item).update();
        });
        return "停用成功！";
    }*/

    @Override
    public List<Long> getSuperId(Long tenantId, List<Long> deptIdList) {
        //1.封装请求参数
        Map<String, Object> param = ApiConst.enableStatusAndUnableDelete();
        param.put("deptIdList", deptIdList);
        param.put("tenantId", tenantId);

        //2.查询数据
        List<DeptPO> deptList = this.baseMapper.getTreeLinkIdByMap(param);

        //3.根据 tree_link_id 判断父子关系
        List<Long> result = new ArrayList<>();
        for (DeptPO deptPO : deptList) {
            boolean match = deptList.stream().anyMatch(item -> !deptPO.getTreeLinkId().equals(item.getTreeLinkId()) && deptPO.getTreeLinkId().contains(item.getTreeLinkId()));
            if (match) {
                result.add(deptPO.getId());
            }
        }
        return result.stream().distinct().collect(Collectors.toList());
    }
}